Skip to content

fix(sandboxes): bound background output retrieval - #862

Open
DamianB-BitFlipper wants to merge 3 commits into
mainfrom
fix/sdk-background-output-burst
Open

fix(sandboxes): bound background output retrieval#862
DamianB-BitFlipper wants to merge 3 commits into
mainfrom
fix/sdk-background-output-burst

Conversation

@DamianB-BitFlipper

@DamianB-BitFlipper DamianB-BitFlipper commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Caps background-job output reads at 20 concurrent requests, retrieves stdout/stderr
sequentially, preserves completed exit codes when output retrieval fails, adds jittered retries and
errno diagnostics, and includes a 100-job concurrency test.

Verification:

  • 82 focused tests passed
  • Ruff checks passed
  • Wheel build passed

Note

Medium Risk
Changes core sandbox client polling, concurrency, and deletion ordering for VM background jobs; behavior is more resilient but callers may see new error fields and different timing under load.

Overview
Splits VM background-job polling from stdout/stderr hydration so latency-sensitive callers can use get_background_job_status / get_background_job_statuses (and batch coalescing) without triggering output downloads; full tails still come from get_background_job / get_background_jobs.

Adds client-wide output coordinators (sync and async) that cap concurrent output work (defaults: 20 active, 200 queued, 64 MiB LRU cache), deduplicate in-flight reads, schedule sandboxes round-robin, and fetch stdout then stderr under a bounded deadline. BackgroundJobStatus now includes stdout_error / stderr_error; when an exit code is known, completed stays true even if a stream could not be retrieved.

Tightens lifecycle around deletion and close: sandbox-scoped leases gain admission checks; delete waits for active work and cancels queued output; async close joins output workers before transports. Read-file retries use jittered backoff and richer diagnostics (nested errno) in API errors.

Reviewed by Cursor Bugbot for commit 822778c. Bugbot is set up for automated code reviews on this repo. Configure here.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8ca296c473

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/prime-sandboxes/src/prime_sandboxes/sandbox.py Outdated
Comment thread packages/prime-sandboxes/src/prime_sandboxes/sandbox.py
Comment thread packages/prime-sandboxes/src/prime_sandboxes/sandbox.py Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 822778c. Configure here.

await asyncio.shield(completion)
except asyncio.CancelledError:
pass

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cancelled fetch poisons later waiters

High Severity

When the last async waiter times out or is cancelled, _detach_waiter aborts the in-flight fetch_task but leaves that operation in _inflight until cleanup finishes. A concurrent get() can join the doomed operation and then raise operation.error, so an innocent caller receives CancelledError instead of output or a retry.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 822778c. Configure here.

self._round_robin.append(job.sandbox_id)
queue.append(operation)
self._pending_count += 1
self._promote_locked()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Queue wait skips inflight dedup

Medium Severity

After waiting for _pending_count to drop below queue_size, both coordinators create a new operation and write _inflight[key] without checking whether another waiter already inserted that key. Two callers for the same job can overwrite each other, break dedup, and run duplicate output reads.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 822778c. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant